 
package com.zdkj.subway.stm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zdkj.common.core.constant.SecurityConstants;
import com.zdkj.common.security.service.PigxUser;
import com.zdkj.common.security.util.SecurityUtils;
import com.zdkj.subway.stm.dto.in.SwMessageDTO;
import com.zdkj.subway.stm.entity.SwParamLine;
import com.zdkj.subway.stm.entity.SwParamStation;
import com.zdkj.subway.stm.entity.SwStInvoiceXaztCheck;
import com.zdkj.subway.stm.enums.InvoiceChechAuditTypeEnum;
import com.zdkj.subway.stm.enums.MessageEnums;
import com.zdkj.subway.stm.fegin.SupportService;
import com.zdkj.subway.stm.mapper.SwParamLineMapper;
import com.zdkj.subway.stm.mapper.SwParamStationMapper;
import com.zdkj.subway.stm.mapper.SwStInvoiceXaztCheckMapper;
import com.zdkj.subway.stm.mapper.SwStPettymoneyCheckMapper;
import com.zdkj.subway.stm.service.SwStInvoiceXaztCheckService;
import com.zdkj.subway.stm.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 西安中铁定额发票盘点
 *
 * @author cxp
 * @date 2024-11-27 20:05:26
 */
@Service
@Slf4j
public class SwStInvoiceXaztCheckServiceImpl extends ServiceImpl<SwStInvoiceXaztCheckMapper, SwStInvoiceXaztCheck> implements SwStInvoiceXaztCheckService {
    private static final int MAX_RECURSION_DEPTH = 12;

    @Autowired
    private SwParamLineMapper swParamLineMapper;

    @Autowired
    private SwParamStationMapper swParamStationMapper;

	@Autowired
    private SwStPettymoneyCheckMapper swStPettymoneyCheckMapper;

    @Autowired
    private SupportService supportService;

    /**
     * 分页查询长安通定额发票盘点
     * @param page
     * @param swStInvoiceXaztCheck
     * @return
     */
    @Override
    public IPage<SwStInvoiceXaztCheck> page(Page page, SwStInvoiceXaztCheck swStInvoiceXaztCheck) {
        LambdaQueryWrapper<SwStInvoiceXaztCheck> queryWrapper = Wrappers.query(swStInvoiceXaztCheck).lambda();
        queryWrapper.orderByDesc(SwStInvoiceXaztCheck::getStatisticsDate).orderByAsc(SwStInvoiceXaztCheck::getStationCode);;
        if(StrUtil.isNotBlank(swStInvoiceXaztCheck.getStatisticsDateStr())) {
            queryWrapper.likeRight(SwStInvoiceXaztCheck::getStatisticsDate, swStInvoiceXaztCheck.getStatisticsDateStr());
        }
        if (!SecurityUtils.getUser().getBelongToLine()) {
            queryWrapper.eq(SwStInvoiceXaztCheck::getLineCode, SecurityUtils.getUser().getLineCode());
            queryWrapper.eq(SwStInvoiceXaztCheck::getStationCode, SecurityUtils.getUser().getStationCode());
        }
        // 查询长安通定额发票盘点
        IPage<SwStInvoiceXaztCheck> resultPage = super.page(page, queryWrapper);
        List<SwStInvoiceXaztCheck> records = new ArrayList<>(resultPage.getRecords());
        // 计算数量
        for (SwStInvoiceXaztCheck record : records) {
            // 上月结存数量
//            Integer unuseBalanceNumber = CalculateUtil.sumOfNumbers(record.getUnuseTwoBalanceNumber(), record.getUnuseThreeBalanceNumber(), record.getUnuseFourBalanceNumber(), record.getUnuseTenBalanceNumber());
            // 已使用数量
            Integer useNumber = CalculateUtil.sumOfNumbers(record.getUseTwoNumber(), record.getUseThreeNumber(), record.getUseFourNumber(), record.getUseTenNumber());
            // 已使用数量
            Integer useCheckNumber = CalculateUtil.sumOfNumbers(record.getUseTwoCheckNumber(), record.getUseThreeCheckNumber(), record.getUseFourCheckNumber(), record.getUseTenCheckNumber());
            // 已使用差异数量
            Integer useDiffNumber = CalculateUtil.sumOfNumbers(record.getUseTwoDiffNumber(), record.getUseThreeDiffNumber(), record.getUseFourDiffNumber(), record.getUseTenDiffNumber());
            // 未使用数量
            Integer unuseNumber = CalculateUtil.sumOfNumbers(record.getUnuseTwoNumber(), record.getUnuseThreeNumber(), record.getUnuseFourNumber(), record.getUnuseTenNumber());
            // 未使用实点数量
            Integer unuseCheckNumber = CalculateUtil.sumOfNumbers(record.getUnuseTwoCheckNumber(), record.getUnuseThreeCheckNumber(), record.getUnuseFourCheckNumber(), record.getUnuseTenCheckNumber());
            // 未使用差异数量
            Integer unuseDiffNumber = CalculateUtil.sumOfNumbers(record.getUnuseTwoDiffNumber(), record.getUnuseThreeDiffNumber(), record.getUnuseFourDiffNumber(), record.getUnuseTenDiffNumber());
            // 未使用部门配发数量
            Integer unuseDispatchNumber = CalculateUtil.sumOfNumbers(record.getUnuseTwoDispatchNumber(), record.getUnuseThreeDispatchNumber(), record.getUnuseFourDispatchNumber(), record.getUnuseTenDispatchNumber());
            // 未使用站间调配数量
            Integer unuseDeployNumber = CalculateUtil.sumOfNumbers(record.getUnuseTwoDeployNumber(), record.getUnuseThreeDeployNumber(), record.getUnuseFourDeployNumber(), record.getUnuseTenDeployNumber());

			// 未使用上交数量
            Integer unuseDeployCompleteNumber = CalculateUtil.sumOfNumbers(record.getUnuseTwoDeployCompleteNumber(), record.getUnuseThreeDeployCompleteNumber(), record.getUnuseFourDeployCompleteNumber(), record.getUnuseTenDeployCompleteNumber());
//            record.setUnuseBalanceNumber(unuseBalanceNumber);
            record.setUseNumber(useNumber);
            record.setUseCheckNumber(useCheckNumber);
            record.setUseDiffNumber(useDiffNumber);
            record.setUnuseNumber(unuseNumber);
            record.setUnuseCheckNumber(unuseCheckNumber);
            record.setUnuseDiffNumber(unuseDiffNumber);
            record.setUnuseDispatchNumber(unuseDispatchNumber);
            record.setUnuseDeployNumber(unuseDeployNumber);
			record.setUnuseDeployCompleteNumber(unuseDeployCompleteNumber);
        }
        resultPage.setRecords(records);
        return resultPage;
    }

    /**
     * 查询前一月盘点数据
     * @param checkTime
     * @param depth
     * @return
     */
    @Override
    public SwStInvoiceXaztCheck getPreviousMonthInvoiceXaztCheck(String checkTime, int depth) {
        // 递归MAX_RECURSION_DEPTH次后任无数据则直接返回
        if(depth > MAX_RECURSION_DEPTH) {
            return null;
        }
        PigxUser user = SecurityUtils.getUser();
        String previousMonth = DateUtilStm.getPreviousMonth(checkTime);
        LambdaQueryWrapper<SwStInvoiceXaztCheck> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SwStInvoiceXaztCheck::getLineCode, user.getLineCode())
                .eq(SwStInvoiceXaztCheck::getStationCode, user.getStationCode())
                .likeRight(SwStInvoiceXaztCheck::getStatisticsDate, previousMonth);
        List<SwStInvoiceXaztCheck> invoiceXaztCheckList = this.list(queryWrapper);
        if(CollectionUtil.isNotEmpty(invoiceXaztCheckList)) {
            return invoiceXaztCheckList.get(0);
        }
        // 递归查询，直至查询到上一个盘点月的数据
        return getPreviousMonthInvoiceXaztCheck(previousMonth, depth + 1);
    }

    /**
     * 新增或修改车站长安通定额发票盘点
     * @param swStInvoiceXaztCheck
     * @return
     */
    @Override
    public boolean saveOrUpdateInvoiceXaztCheck(SwStInvoiceXaztCheck swStInvoiceXaztCheck) {
        PigxUser user = SecurityUtils.getUser();
        swStInvoiceXaztCheck.setLineCode(user.getLineCode());
        swStInvoiceXaztCheck.setStationCode(user.getStationCode());
        // 查询车站盘点日期的长安通定额发票盘点数据是否存在
        LambdaQueryWrapper<SwStInvoiceXaztCheck> newStationincome = Wrappers.<SwStInvoiceXaztCheck>lambdaQuery()
                .eq(SwStInvoiceXaztCheck::getLineCode, swStInvoiceXaztCheck.getLineCode())
                .eq(SwStInvoiceXaztCheck::getStationCode, swStInvoiceXaztCheck.getStationCode())
                .eq(SwStInvoiceXaztCheck::getDelFlag, "0")
                .eq(SwStInvoiceXaztCheck::getStatisticsDate, swStInvoiceXaztCheck.getStatisticsDate());
        SwStInvoiceXaztCheck stInvoiceXaztCheck = this.getOne(newStationincome);
        // 重新计算数量和金额合计
        calculateAmount(swStInvoiceXaztCheck);
        if (ObjectUtil.isNotEmpty(stInvoiceXaztCheck)) {
            // 修改长安通定额发票盘点
            swStInvoiceXaztCheck.setId(stInvoiceXaztCheck.getId());
            return this.updateById(swStInvoiceXaztCheck);
        }
        // 保存长安通定额发票盘点
        swStInvoiceXaztCheck.setCheckStatus("0");
        return this.save(swStInvoiceXaztCheck);
    }

    /**
     * 长安通定额发票盘点数据批量提交
     * @param ids
     * @param status
     * @return
     */
    @Override
    public boolean updateApprovalStatus(List<Integer> ids, String status, String auditType) {
        if (CollectionUtils.isEmpty(ids)) {
            return false;
        }
        List<SwStInvoiceXaztCheck> updateData = new ArrayList<>();
        PigxUser user = SecurityUtils.getUser();
        for (Integer id : ids) {
         	
			SwStInvoiceXaztCheck stInvoiceXaztCheck = this.getById(id);
			/*
			 SwStInvoiceXaztCheck stInvoiceXaztCheck = new SwStInvoiceXaztCheck();
             stInvoiceXaztCheck.setId(Long.valueOf(id));
			*/
            stInvoiceXaztCheck.setCheckStatus(status);
            // SwStInvoiceXaztCheck swStInvoiceXaztCheck = baseMapper.selectById(id);
            QueryWrapper<SwParamStation> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("CODE", stInvoiceXaztCheck.getStationCode());
            SwParamStation swParamStation = swParamStationMapper.selectOne(queryWrapper);

            // 格式化日期
            LocalDate statisticsDate = stInvoiceXaztCheck.getStatisticsDate();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月");
            String formattedDate = statisticsDate.format(formatter);

            SwMessageDTO swMessageDTO = new SwMessageDTO();
            swMessageDTO.setTitle(formattedDate+swParamStation.getName()+" 中铁冠名定额发票盘点数据审核");
            swMessageDTO.setMsgType("审批");
            swMessageDTO.setCreatorName(user.getNikeName());
            swMessageDTO.setCreatorId(user.getId());

			UpdateWrapper<SwStInvoiceXaztCheck> updateWrapper=new UpdateWrapper<>();

            if (status.equals("1")){
                swMessageDTO.setLineCode(stInvoiceXaztCheck.getLineCode());
                swMessageDTO.setStationCode(stInvoiceXaztCheck.getStationCode());
                swMessageDTO.setUrl(MessageEnums.MessageUrlEnums.STATION_APPROVAL_ZT_INVOICE_STATUS_URL.getUrl());
                swMessageDTO.setRoleCode(MessageEnums.ZXZZ_ROLE_CODE.getCode().toString());
                swMessageDTO.setContent("车站提交，站长待审核");
				//后续审核人员置空
				stInvoiceXaztCheck.setAuditStationName("");
                stInvoiceXaztCheck.setAuditStationJobNo("");  
				stInvoiceXaztCheck.setAuditWorkshopName("");
                stInvoiceXaztCheck.setAuditWorkshopJobNo("");
				stInvoiceXaztCheck.setAuditDeptName("");
                stInvoiceXaztCheck.setAuditDeptJobNo("");

				updateWrapper.set("AUDIT_STATION_TIME", null); // 或者用lambda方式
				updateWrapper.set("AUDIT_WORKSHOP_TIME", null); // 或者用lambda方式
				updateWrapper.set("AUDIT_DEPT_TIME", null); // 或者用lambda方式
            } else if (status.equals("2")){
                swMessageDTO.setLineCode(stInvoiceXaztCheck.getLineCode());
                swMessageDTO.setStationCode(stInvoiceXaztCheck.getStationCode());
                swMessageDTO.setUrl(MessageEnums.MessageUrlEnums.STATION_APPROVAL_ZT_INVOICE_STATUS_URL.getUrl());
                swMessageDTO.setContent("站长驳回");
				//后续审核人员置空
				stInvoiceXaztCheck.setAuditWorkshopName("");
                stInvoiceXaztCheck.setAuditWorkshopJobNo("");
				stInvoiceXaztCheck.setAuditDeptName("");
                stInvoiceXaztCheck.setAuditDeptJobNo("");

				updateWrapper.set("AUDIT_WORKSHOP_TIME", null); // 或者用lambda方式
				updateWrapper.set("AUDIT_DEPT_TIME", null); // 或者用lambda方式
            }else if (status.equals("3")){
                swMessageDTO.setDeptId(MessageEnums.WORKSHOP_DEPT_ID.getCode());//站务车间
                swMessageDTO.setUrl(MessageEnums.MessageUrlEnums.DEPT_APPROVAL_ZT_INVOICE_STATUS_URL.getUrl());
                swMessageDTO.setRoleCode(MessageEnums.ZWPWGL_ROLE_CODE.getCode().toString());
                swMessageDTO.setContent("站长审核通过，车间票务专业待审核");

				updateWrapper.set("AUDIT_WORKSHOP_TIME", null); // 或者用lambda方式
				updateWrapper.set("AUDIT_DEPT_TIME", null); // 或者用lambda方式
            } else if (status.equals("4")) {
                swMessageDTO.setLineCode(stInvoiceXaztCheck.getLineCode());
                swMessageDTO.setStationCode(stInvoiceXaztCheck.getStationCode());
                swMessageDTO.setUrl(MessageEnums.MessageUrlEnums.STATION_APPROVAL_ZT_INVOICE_STATUS_URL.getUrl());
                swMessageDTO.setRoleCode(MessageEnums.ZXZZ_ROLE_CODE.getCode().toString());
                swMessageDTO.setContent("车间票务专业驳回，站长待审核");
				//后续审核人员置空				
				stInvoiceXaztCheck.setAuditDeptName("");
                stInvoiceXaztCheck.setAuditDeptJobNo("");
				updateWrapper.set("AUDIT_DEPT_TIME", null); // 或者用lambda方式
            } else if (status.equals("5")){
                swMessageDTO.setDeptId(MessageEnums.AUDIT_DEPT_ID.getCode());//安全技术室
                swMessageDTO.setUrl(MessageEnums.MessageUrlEnums.DEPT_APPROVAL_ZT_INVOICE_STATUS_URL.getUrl());
                swMessageDTO.setRoleCode(MessageEnums.PWGLJSRY_ROLE_CODE.getCode().toString());
                swMessageDTO.setContent("车间票务专业审核通过，部门票务专业待审核");
            } else if (status.equals("6")) {
                swMessageDTO.setDeptId(MessageEnums.WORKSHOP_DEPT_ID.getCode());//站务车间
                swMessageDTO.setUrl(MessageEnums.MessageUrlEnums.DEPT_APPROVAL_ZT_INVOICE_STATUS_URL.getUrl());
                swMessageDTO.setRoleCode(MessageEnums.ZWPWGL_ROLE_CODE.getCode().toString());
                swMessageDTO.setContent("部门票务专业驳回，车间票务专业待审核");
            }

            log.info("中铁冠名定额定额发票盘点数据审核==>id:{},status:{},auditType:{},nikeName:{},time:{},oldStatus:{}", id, status,auditType,user.getNikeName(),new Date(),stInvoiceXaztCheck.getCheckStatus());
            //盘点提交状态 0：未提交 1：已提交 2：车站驳回 3：车站审核通过 4.车间驳回 5.车间审核通过 6：部门驳回 7：部门审核通过
            if (InvoiceChechAuditTypeEnum.AUDIT_STATION.getCode().equals(auditType)) { // 中心站长审核
                stInvoiceXaztCheck.setAuditStationName(user.getNikeName());
                stInvoiceXaztCheck.setAuditStationJobNo(user.getUserCode());
                stInvoiceXaztCheck.setAuditStationTime(LocalDateTime.now());
				//后续审核人员置空
				stInvoiceXaztCheck.setAuditWorkshopName("");
                stInvoiceXaztCheck.setAuditWorkshopJobNo("");
				stInvoiceXaztCheck.setAuditDeptName("");
                stInvoiceXaztCheck.setAuditDeptJobNo("");
            } else if(InvoiceChechAuditTypeEnum.AUDIT_WORKSHOP.getCode().equals(auditType)) { // 车间票务专业审核
                stInvoiceXaztCheck.setAuditWorkshopName(user.getNikeName());
                stInvoiceXaztCheck.setAuditWorkshopJobNo(user.getUserCode());
                stInvoiceXaztCheck.setAuditWorkshopTime(LocalDateTime.now());
				//后续审核人员置空
				stInvoiceXaztCheck.setAuditDeptName("");
                stInvoiceXaztCheck.setAuditDeptJobNo("");
            } else if(InvoiceChechAuditTypeEnum.AUDIT_DEPT.getCode().equals(auditType)) { // 部门票务专业审核
                stInvoiceXaztCheck.setAuditDeptName(user.getNikeName());
                stInvoiceXaztCheck.setAuditDeptJobNo(user.getUserCode());
                stInvoiceXaztCheck.setAuditDeptTime(LocalDateTime.now());
            }
			 //updateData.add(stInvoiceXaztCheck);
			//UpdateWrapper<SwStInvoiceXaztCheck> updateWrapper=new UpdateWrapper<>();
			updateWrapper.eq("id", id);
			this.update(stInvoiceXaztCheck, updateWrapper);
            supportService.saveInner(swMessageDTO, SecurityConstants.FROM_IN);
           
        }
        return true;//updateBatchById(updateData);
    }

    /**
     * 车站导出长安通定额发票盘点表
     * @param id
     * @param response
     */
    @Override
    public void exportInvoiceXaztCheckForStation(Long id, HttpServletResponse response) {
        InputStream excelTemplate = null;
        if (ObjectUtil.isNotEmpty(id)) {
            SwStInvoiceXaztCheck invoiceXaztCheck = this.getById(id);
            try {

				// 格式化日期
                LocalDate statisticsDate = invoiceXaztCheck.getStatisticsDate();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月");
                String formattedDate = statisticsDate.format(formatter);

				// 查询车站名称
                JSONObject jsonObject = getlinenameOrStationName(invoiceXaztCheck.getLineCode(), invoiceXaztCheck.getStationCode());
                String stationName = jsonObject.getString("stationName");

                response.setContentType("application/vnd.ms-excel");
                response.setCharacterEncoding("utf-8");

				final String fileName = URLEncoder.encode("西安中铁轨道交通有限公司冠名定额发票盘点表-"+stationName +"-" + formattedDate, "UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
                /*
                final String fileName = URLEncoder.encode("西安中铁轨道交通有限公司冠名定额发票盘点表", "UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx");
                */
                excelTemplate = this.getClass().getResourceAsStream("/static/excel/template/SwStInvoiceXaztCheckExcelTemplate.xlsx");

                ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerConverter(new LocalDateTimeConverter()).registerConverter(new LocalDateConverter()).withTemplate(excelTemplate).build();
                WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build();

                Map<String, Object> map = BeanUtil.beanToMap(invoiceXaztCheck);

              
                map.put("statisticsDate", formattedDate);
                
                map.put("stationName", stationName);
                // 生成流水号
                SerialNumberGenerator serialNumber = new SerialNumberGenerator();
                map.put("serialNumber", serialNumber.generateSerialNumber());

                excelWriter.fill(map, writeSheet);
                excelWriter.finish();
            }  catch (Exception e) {
                e.printStackTrace();
            } finally {
                if(excelTemplate != null){
                    try {
                        excelTemplate.close();
                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                    }

                }
            }
        }
    }

	 /**
     * 车站导出长安通定额发票盘点表--所有车站多个Sheet
     * @param checkTime
     * @param response
     */
    @Override
    public void exportInvoiceXaztCheckForStationAll(String checkTime, HttpServletResponse response) {      
        if (ObjectUtil.isNotEmpty(checkTime)) {
            // 查询要导出的车站备用金盘点数据
			LambdaQueryWrapper<SwStInvoiceXaztCheck> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.apply("date_format(STATISTICS_DATE,'%Y-%m') = '" + checkTime+"'");
						
			queryWrapper.orderByDesc(SwStInvoiceXaztCheck::getStatisticsDate).orderByAsc(SwStInvoiceXaztCheck::getStationCode);
			List<SwStInvoiceXaztCheck> records = this.list(queryWrapper);
			
            InputStream excelTemplateIs = null;
            try {
                 //获取已有的车站数据
				Map<String,SwStInvoiceXaztCheck> mapHaveData = new HashMap();
				String formattedDate = "";
               
				if(records!=null && records.size()>0){
					
				   SwStInvoiceXaztCheck data0 = records.get(0);
					// 格式化日期
                   LocalDate statisticsDate = data0.getStatisticsDate();
				  
                   DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月");
                   formattedDate = statisticsDate.format(formatter);
				}
				records.forEach(item -> {
					// 查询车站名称
					JSONObject jsonObject = getlinenameOrStationName(item.getLineCode(), item.getStationCode());
					//设置盘点时间改为年月
					item.setStatisticsDateStr(DateUtilStm.localDateToString(item.getStatisticsDate(),"yyyy-MM"));
					item.setStationCode(jsonObject.getString("stationName"));
                   	mapHaveData.put(jsonObject.getString("stationName"),item); //key车站名字
			   });
				
              
                response.reset(); // 非常重要
                response.setContentType("application/vnd.ms-excel");
                response.setCharacterEncoding("utf-8");

				final String fileName = URLEncoder.encode("西安中铁轨道交通有限公司冠名定额发票盘点表(全部车站)"+"-" + formattedDate, "UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
                /*
                final String fileName = URLEncoder.encode("西安中铁轨道交通有限公司冠名定额发票盘点表", "UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xlsx");
                */
                excelTemplateIs = this.getClass().getResourceAsStream("/static/excel/template/SwStInvoiceXaztCheckAllStationExcelTemplate.xlsx");
                
				ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerConverter(new LocalDateTimeConverter()).registerConverter(new LocalDateConverter()).withTemplate(excelTemplateIs).build();
			    
				List<Map<String,String>> stationMap = swStPettymoneyCheckMapper.selectStationMap();        
               //车站循环,每个车站对应一个对象，为导出做准备
			   int i=0;//计数器，创建了多少个Sheet
			   for (Map<String,String> mapStations : stationMap) {
					String stationCode = mapStations.get("CODE");
					String stationName = mapStations.get("NAME");                    
					 i++;
					 SwStInvoiceXaztCheck entityExport = new SwStInvoiceXaztCheck();
					 boolean isExist = false;
					 if(mapHaveData!=null){
					    if(mapHaveData.containsKey(stationName)){
							isExist =true;
							entityExport = mapHaveData.get(stationName);                            
					    }
					}
					if(!isExist){
						entityExport.setStatisticsDateStr(formattedDate);					    
					}
					entityExport.setStationCode(stationName);
					
					Map<String, Object> map = BeanUtil.beanToMap(entityExport);
                    map.put("statisticsDate", formattedDate);
                    map.put("stationName", stationName);					
					WriteSheet writeSheet = EasyExcel.writerSheet(i-1,stationName).build();                   
                    excelWriter.fill(map,writeSheet);					
				 }
				
                excelWriter.finish();
            }  catch (Exception e) {
                e.printStackTrace();
				log.info("导出西安中铁轨道交通有限公司冠名定额发票盘点表出错"+e.getMessage());
            } finally {
                if(excelTemplateIs != null){
                    try {
                        excelTemplateIs.close();
                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                    }

                }
            }
        }
    }

    /**
     * 查询要导出的西安中铁定额发票盘点数据
     * @param statisticsDate
     * @param stationCodes
     * @return
     */
    @Override
    public List<SwStInvoiceXaztCheck> getInvoiceXaztCheckRecords(String statisticsDate, List<String> stationCodes) {
        LambdaQueryWrapper<SwStInvoiceXaztCheck> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(statisticsDate)) {
            queryWrapper.likeRight(SwStInvoiceXaztCheck::getStatisticsDate, statisticsDate);
        }
        if (ObjectUtil.isNotEmpty(stationCodes)) {
            queryWrapper.in(SwStInvoiceXaztCheck::getStationCode, stationCodes);
        }
        //queryWrapper.orderByDesc(SwStInvoiceXaztCheck::getStatisticsDate);
		queryWrapper.orderByDesc(SwStInvoiceXaztCheck::getStatisticsDate).orderByAsc(SwStInvoiceXaztCheck::getStationCode);	
        List<SwStInvoiceXaztCheck> list = this.list(queryWrapper);
        list.forEach(item -> {
            // 查询车站名称
            JSONObject jsonObject = getlinenameOrStationName(item.getLineCode(), item.getStationCode());
            item.setStationName(jsonObject.getString("stationName"));
        });
        return list;
    }

    /**
     * 处理西安中铁盘点数据
     * @param invoiceXaztCheckList
     * @return
     */
    @Override
    public Map<String, Map<LocalDate, List<Integer>>> processData(List<SwStInvoiceXaztCheck> invoiceXaztCheckList) {
        Map<String, Map<LocalDate, List<Integer>>> processedData = new LinkedHashMap<>();
        for (SwStInvoiceXaztCheck invoiceXaztCheck : invoiceXaztCheckList) {
            String station = invoiceXaztCheck.getStationName();
            LocalDate statisticsDate = invoiceXaztCheck.getStatisticsDate();

            if (!processedData.containsKey(station)) {
                processedData.put(station, new HashMap<>());
            }

            Map<LocalDate, List<Integer>> stationData = processedData.get(station);
            if (!stationData.containsKey(statisticsDate)) {
                stationData.put(statisticsDate, new ArrayList<>(Collections.nCopies(20, 0)));
            }

            List<Integer> monthData = stationData.get(statisticsDate);
            monthData.set(0, invoiceXaztCheck.getUnuseTwoDispatchNumber());
            monthData.set(1, invoiceXaztCheck.getUnuseTwoDeployNumber());
			monthData.set(2, invoiceXaztCheck.getUnuseTwoDeployCompleteNumber());
            monthData.set(3, invoiceXaztCheck.getUseTwoCheckNumber());
            monthData.set(4, invoiceXaztCheck.getUnuseTwoCheckNumber());
            monthData.set(5, invoiceXaztCheck.getUnuseThreeDispatchNumber());
            monthData.set(6, invoiceXaztCheck.getUnuseThreeDeployNumber());
			monthData.set(7, invoiceXaztCheck.getUnuseThreeDeployCompleteNumber());
            monthData.set(8, invoiceXaztCheck.getUseThreeCheckNumber());
            monthData.set(9, invoiceXaztCheck.getUnuseThreeCheckNumber());
            monthData.set(10, invoiceXaztCheck.getUnuseFourDispatchNumber());
            monthData.set(11, invoiceXaztCheck.getUnuseFourDeployNumber());
			monthData.set(12, invoiceXaztCheck.getUnuseFourDeployCompleteNumber());
            monthData.set(13, invoiceXaztCheck.getUseFourCheckNumber());
            monthData.set(14, invoiceXaztCheck.getUnuseFourCheckNumber());
            monthData.set(15, invoiceXaztCheck.getUnuseTenDispatchNumber());
            monthData.set(16, invoiceXaztCheck.getUnuseTenDeployNumber());
			monthData.set(17, invoiceXaztCheck.getUnuseTenDeployCompleteNumber());
            monthData.set(18, invoiceXaztCheck.getUseTenCheckNumber());
            monthData.set(19, invoiceXaztCheck.getUnuseTenCheckNumber());
        }
        return processedData;
    }

    /**
     * 数量和金额计算
     * @param swStInvoiceXaztCheck
     */
    private void calculateAmount(SwStInvoiceXaztCheck swStInvoiceXaztCheck) {
        // 2元未使用金额合计
        BigDecimal unuseTwoMoney = BigDecimal.valueOf(Optional.ofNullable(swStInvoiceXaztCheck.getUnuseTwoNumber()).orElse(0) * 2L);
        // 3元未使用金额合计
        BigDecimal unuseThreeMoney = BigDecimal.valueOf(Optional.ofNullable(swStInvoiceXaztCheck.getUnuseThreeNumber()).orElse(0) * 3L);
        // 4元未使用金额合计
        BigDecimal unuseFourMoney = BigDecimal.valueOf(Optional.ofNullable(swStInvoiceXaztCheck.getUnuseFourNumber()).orElse(0) * 4L);
        // 10元未使用金额合计
        BigDecimal unuseTenMoney = BigDecimal.valueOf(Optional.ofNullable(swStInvoiceXaztCheck.getUnuseTenNumber()).orElse(0) * 10L);

        // 2元未使用差异数量
        int unuseTwoDiffNumber = Optional.ofNullable(swStInvoiceXaztCheck.getUnuseTwoCheckNumber()).orElse(0) - Optional.ofNullable(swStInvoiceXaztCheck.getUnuseTwoNumber()).orElse(0);
        // 3元未使用差异数量
        int unuseThreeDiffNumber = Optional.ofNullable(swStInvoiceXaztCheck.getUnuseThreeCheckNumber()).orElse(0) - Optional.ofNullable(swStInvoiceXaztCheck.getUnuseThreeNumber()).orElse(0);
        // 4元未使用差异数量
        int unuseFourDiffNumber = Optional.ofNullable(swStInvoiceXaztCheck.getUnuseFourCheckNumber()).orElse(0) - Optional.ofNullable(swStInvoiceXaztCheck.getUnuseFourNumber()).orElse(0);
        // 10元未使用差异数量
        int unuseTenDiffNumber = Optional.ofNullable(swStInvoiceXaztCheck.getUnuseTenCheckNumber()).orElse(0) - Optional.ofNullable(swStInvoiceXaztCheck.getUnuseTenNumber()).orElse(0);

        swStInvoiceXaztCheck.setUnuseTwoMoney(unuseTwoMoney);
        swStInvoiceXaztCheck.setUnuseThreeMoney(unuseThreeMoney);
        swStInvoiceXaztCheck.setUnuseFourMoney(unuseFourMoney);
        swStInvoiceXaztCheck.setUnuseTenMoney(unuseTenMoney);
        swStInvoiceXaztCheck.setUnuseTwoDiffNumber(unuseTwoDiffNumber);
        swStInvoiceXaztCheck.setUnuseThreeDiffNumber(unuseThreeDiffNumber);
        swStInvoiceXaztCheck.setUnuseFourDiffNumber(unuseFourDiffNumber);
        swStInvoiceXaztCheck.setUnuseTenDiffNumber(unuseTenDiffNumber);

        // 2元使用金额合计
        BigDecimal useTwoMoney = BigDecimal.valueOf(Optional.ofNullable(swStInvoiceXaztCheck.getUseTwoNumber()).orElse(0) * 2);
        // 3元使用金额合计
        BigDecimal useThreeMoney = BigDecimal.valueOf(Optional.ofNullable(swStInvoiceXaztCheck.getUseThreeNumber()).orElse(0) * 3);
        // 4元使用金额合计
        BigDecimal useFourMoney = BigDecimal.valueOf(Optional.ofNullable(swStInvoiceXaztCheck.getUseFourNumber()).orElse(0) * 4);
        // 10元使用金额合计
        BigDecimal useTenMoney = BigDecimal.valueOf(Optional.ofNullable(swStInvoiceXaztCheck.getUseTenNumber()).orElse(0) * 10);

        swStInvoiceXaztCheck.setUseTwoMoney(useTwoMoney);
        swStInvoiceXaztCheck.setUseThreeMoney(useThreeMoney);
        swStInvoiceXaztCheck.setUseFourMoney(useFourMoney);
        swStInvoiceXaztCheck.setUseTenMoney(useTenMoney);
    }

    /**
     * 获取线路名称&车站名称
     * @param lineCode
     * @param stationCode
     * @return
     */
    public JSONObject getlinenameOrStationName(String lineCode, String stationCode) {
        JSONObject object = new JSONObject();
        QueryWrapper<SwParamLine> queryWrapperLine = new QueryWrapper<>();
        queryWrapperLine.lambda().eq(SwParamLine::getCode, lineCode);
        List<SwParamLine> swParamLines = swParamLineMapper.selectList(queryWrapperLine);
        if (CollectionUtil.isNotEmpty(swParamLines)) {
            lineCode = swParamLines.get(0).getCode();
            object.put("lineName", swParamLines.get(0).getName());
            QueryWrapper<SwParamStation> queryWrapperStation = new QueryWrapper<>();
            queryWrapperStation.lambda().eq(SwParamStation::getLineCode, lineCode)
                    .eq(SwParamStation::getCode, stationCode);
            List<SwParamStation> swParamStations = swParamStationMapper.selectList(queryWrapperStation);
            if (CollectionUtil.isNotEmpty(swParamStations)) {
                object.put("stationName", swParamStations.get(0).getName());
            }
        }
        return object;
    }
}
